package com.znf4.page;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.Assert;

import com.znf4.entity.BaseEntity;

/** 
 * 类功能说明：结合B-JUI框架的分页工具类
 * 版本：V1.0
 */
public class Page {
	
	/**
	 * 默认构造方法
	 */
	private Page(){}
	
	/**
	 * 函数功能说明 ： 根据总记录数，对页面传来的分页参数进行校验，并返分页的SQL语句<br/>
	 * 参数：@param totalCount 总记录数
	 * 参数：@param pageParam 分页参数
	 * 参数：@return <br/>
	 * return：String <br/>
	 */
	public static String limitSql(int totalCount, PageParam pageParam) {
		// 校验当前页数
		int pageNum = Page.checkPageCurrent(totalCount, pageParam.getPageNum(), pageParam.getNumPerPage());
		pageParam.setPageNum(pageNum); // 为当前页重新设值	
		int numPerPage = Page.checkPageSize(pageParam.getNumPerPage()); // 校验每页记录数
		pageParam.setNumPerPage(numPerPage);   // 重新设值
		return Page.limitSql(pageNum, numPerPage);
	}
	
	/**
	 * 函数功能说明 ：校验当前页数currentPage.<br/>
	 * 1、先根据总记录数totalCount和每页记录数numPerPage，计算出总页数totalPage.<br/>
	 * 2、判断页面提交过来的当前页数currentPage是否大于总页数totalPage，大于则返回totalPage.<br/>
	 * 3、判断currentPage是否小于1，小于则返回1.<br/>
	 * 4、其它则直接返回currentPage . <br/>
	 * 参数：@param totalCount 总记录数
	 * 参数：@param pageCurrent 当前页
	 * 参数：@param pageSize 每页记录数
	 * 参数：@return <br/>
	 */
	public static int checkPageCurrent(int totalCount, int pageCurrent, int pageSize){
		int totalPage = Page.countTotalPage(totalCount, pageSize); // 最大页数
		if(pageCurrent > totalPage){
			// 如果页面提交过来的页数大于总页数，则将当前页设为总页数
			//此时要求totalPage要大于获等于1
			if (totalPage < 1){
				return 1; 
			}
			return totalPage; 
		}else if (pageCurrent < 1){
			return 1;         // 当前页不能小于1（避免页面输入不正确值）
		}else{
			return pageCurrent;
		}
	}
	
	/**
	 * 函数功能说明 ：计算总页数
	 * 参数：@param totalCount 总记录数
	 * 参数：@param pageSize 每页记录数
	 * 参数：@return
	 */
	public static int countTotalPage(final int totalCount, final int pageSize) {
		if (totalCount % pageSize == 0) {
			return totalCount / pageSize; // 刚好整除
		} else {
			return totalCount / pageSize + 1; // 不能整除则总页数为：商 + 1
		}
	}
	
	/**
	 * 函数功能说明 ：获取分页用的limit SQL语句段
	 * 参数：@param pageCurrent 当前页
	 * 参数：@param pageSize 每页记录数
	 * 参数：@return <br/>
	 * return：String <br/>
	 */
	public static String limitSql(int pageCurrent, int pageSize) {
		return " limit " + Page.countOffset(pageCurrent, pageSize) + "," + pageSize;
	}
	
	/**
	 * 函数功能说明 ：计算当前分页的开始记录的索引
	 * 参数：@param pageCurrent 当前页
	 * 参数：@param pageSize 每页记录数
	 * 参数：@return <br/>
	 * return：int <br/>
	 */
	public static int countOffset(final int pageCurrent, final int pageSize) {
		return (pageCurrent - 1) * pageSize;
	}
	
	/**
	 * 函数功能说明 ： 校验页面输入的每页记录数pageSize是否合法 .<br/>
	 * 1、当页面输入的每页记录数pageSize大于允许的最大每页记录数MAX_PAGE_SIZE时，返回MAX_PAGE_SIZE.<br/>
	 * 2、如果pageSize小于1，则返回默认的每页记录数DEFAULT_PAGE_SIZE.<br/>
	 * 参数：@param pageSize 页面输入的每页记录数<br/>
	 * 参数：@return <br/>
	 * return：int <br/>
	 */
	public static int checkPageSize(int pageSize){
		if(pageSize > PageParam.MAX_PAGE_SIZE){
			return PageParam.MAX_PAGE_SIZE;
		}else if (pageSize < 1){
			return PageParam.DEFAULT_PAGE_NUM;
		}else{
			return pageSize;
		}
	}
	
	/**
	 * 函数功能说明 ： 根据分页查询的SQL语句，获取统计总记录数的语句
	 * 参数：@param sql
	 * 参数：@return <br/>
	 * return：String <br/>
	 */
	public static String countSql(String sql){
		Assert.hasText(sql,"分页SQL语句不能为空");
		String countSql =  sql.substring(sql.indexOf("from")); // 去除第一个from前的内容
		return "select count(*) " + removeOrderBy(countSql);
	}
	
	/**
	 * 函数功能说明 ：移除SQL语句中的的order by子句（用于分页前获取总记录数，不需要排序） <br/>
	 * 参数：@param sql
	 * 参数：@return <br/>
	 * return：String <br/>
	 */
	public static String removeOrderBy(String sql) {
		Assert.hasText(sql);
		Pattern pat = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
		Matcher mc = pat.matcher(sql);
		StringBuffer strBuf = new StringBuffer();
		while (mc.find()) {
			mc.appendReplacement(strBuf, "");
		}
		mc.appendTail(strBuf);
		return strBuf.toString();
	}
	
	
	
	
	/**
     * 分页查询数据 .
     * 
     * pageParam:分页用
     * 
     * totalCount：总记录数
     * 
     * list ：要分页展示的数据
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public PageBean listPage(PageParam pageParam,Long totalCount,List<Object> list, Map<String, Object> countResultMap ) {

        // 统计总记录数
//        Long totalCount = sessionTemplate.selectOne(getStatement(SQL_LIST_PAGE_COUNT), paramMap);

        // 校验当前页数
        int currentPage = PageBean.checkCurrentPage(totalCount.intValue(), pageParam.getNumPerPage(), pageParam.getPageNum());
        pageParam.setPageNum(currentPage); // 为当前页重新设值
        // 校验页面输入的每页记录数numPerPage是否合法
        int numPerPage = PageBean.checkNumPerPage(pageParam.getNumPerPage()); // 校验每页记录数
        pageParam.setNumPerPage(numPerPage); // 重新设值

        // 获取分页数据集
//        List<Object> list = sessionTemplate.selectList(getStatement(SQL_LIST_PAGE), paramMap);

        // 构造分页对象
        return new PageBean(pageParam.getPageNum(), pageParam.getNumPerPage(), totalCount.intValue(), list);
    }

    /**
     * 函数功能说明 ： 设置分页条件.
     * 
     */
    public void setPageParam(PageParam pageParam , BaseEntity baseEntity) {
    	// 根据页面传来的分页参数构造SQL分页参数
    	baseEntity.setPageFirst((pageParam.getPageNum() - 1) * pageParam.getNumPerPage()+"");
    	baseEntity.setPageSize((pageParam.getPageNum() - 1) * pageParam.getNumPerPage()+"") ;
    	baseEntity.setStartRowNum((pageParam.getPageNum() - 1) * pageParam.getNumPerPage()+"");
    	baseEntity.setEndRowNum(pageParam.getPageNum() * pageParam.getNumPerPage()+"");
    }
    /**
     * 函数功能说明 ： 获取Mapper命名空间.
     * 
     * @参数：@param sqlId
     * @参数：@return
     * @return：String
     * @throws
     */
    public String getStatement(String sqlId) {
        String name = this.getClass().getName();
        // 单线程用StringBuilder，确保速度；多线程用StringBuffer,确保安全
        StringBuilder sb = new StringBuilder();
        sb.append(name).append(".").append(sqlId);
        return sb.toString();
    }
	
    
    
	
	
	
	
	
}
